Skip to content

[DreamNextGen] AMLogic audio + video backend fixes - #3

Merged
atvcaptain merged 3 commits into
oe-alliance:masterfrom
WXbet:aml-audio-fixes
Jun 17, 2026
Merged

atvcaptain merged 3 commits into
oe-alliance:masterfrom
WXbet:aml-audio-fixes

Conversation

@WXbet

@WXbet WXbet commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

New output adapters that route exteplayer3 directly through the Dreambox- private DVB-API + ALSA, matching the runtime behaviour of dreamvideosink / dreamaudiosink as observed by strace. Replaces the BCM-style writer chain for the AML targets; enabled by --enable-dreamnextgen.

output/dream_video.c

  • VIDEO_SET_DEC_SYSINFO (48 B struct) + VIDEO_SET_FRAME (168 B struct, GstClockTime-style pts) on /dev/dvb/adapter0/video0
  • H.264 / H.265 / MPEG1/2 streamtype + dec_format mapping
  • Producer/consumer ring (256 slots) between FFMPEGThread and a dv_consumer thread; consumer burst-submits frames so the kernel ringbuffer carries 3-4 frames ahead (vstream_cache ~ 250 kB, buf_avail_num ~ 3) instead of the just-in-time 12 kB / buf=0 we got from a per-frame pacer. EAGAIN + poll(50 ms, 250 ms giveup) on /dev/dvb/.../video0 + /dev/amvideo_poll is the back-pressure
  • Stream PTS used directly so tsync's pts_video stays in the same timebase as pts_audio; monotonic 90 kHz fallback only when fr_pts < 0
  • VIDEO_GET_EVENT drain before SET_FRAME, VIDEO_GET_PTS after — mirrors dreamvideosink strace pattern. disable_video=0 on open, no freerun_mode / show_first_frame_nosync touch (also matches strace)
  • OUTPUT_FLUSH / OUTPUT_CLEAR drains the queue, VIDEO_CLEAR_BUFFER, writes tsync/discontinue=1
  • Dual logging (stderr + /tmp/dream_video.log) because serviceapp's PlayerApp::stderrAvail filters non-JSON stderr out of the e2 debug log

output/dream_audio.c

  • ALSA PCM output on the dreamhdmi / dreamspdif / dreambt slave (selected by /sys/class/amhdmitx/amhdmitx0/audio_source)
  • FFmpeg software decoder feeding interleaved S16; rate / channels from pcmPrivateData_t shipped through extradata by container_ffmpeg.c
  • Producer/consumer queue (128 slots, 500 ms bounded push wait) between DreamAudioWrite (on FFMPEGThread) and a da_consumer thread; consumer owns the ALSA handle + drift logic so the demuxer never blocks in snd_pcm_writei. Solves the AAC drain-storm we measured on AAC live-TV AML mirrors (~30% drops without queue, ~5% with)
  • Match dreamaudiosink runtime: tsync ENABLED in PCRMASTER (mode=2), /proc/stb/pcr_offset = 0x0 + auto_pcr_offset = 0x0, pts_audio / pts_video wiped on Open, signal tsync/discontinue. AMASTER caused the kernel to release video at the audio-chunk arrival rate (~50 fps for our 20 ms chunks) and drop ~33% of 25 fps frames — visible as the "gefesselt" stutter
  • Initial anchor on the first chunk after Open / Flush / Switch:
    • |lead| > 2000ms → ALSA flush, drop buffer (1s throttle)
    • lead in (+50, +2000]ms → push lead silence (cap 2000)
    • lead in [-3000, -50)ms → queue (-lead) bytes of skip budget
      Sustained-lag re-arm once anchor disarmed: |av_ms| > 1000 held 2s
      re-arms (5s cooldown). 30s heartbeat log; no per-write logging.
  • da_reset_anchor_locked() called from Stop / Flush / Switch — mirror
    of dream_alsa_reset_anchor(). Without it, post-seek the drift code
    computed apts_speaker vs a stale pts_video (kernel display still on
    the pre-seek frame until the first I-frame decodes)
  • Decoded audio rate compared against a separate m_alsa_dec_rate so
    the HW-promoted rate from snd_pcm_hw_params_set_rate_near
    (44100 → 48000) doesn't trigger a configure-loop on AAC 44.1 kHz
    Live-TV streams
  • IEC61937 passthrough for AC3 / EAC3 / DTS via byte-swap into a
    static SPDIF buffer; TrueHD / DTS-HD MA HBR via a libavformat spdif
    muxer producing whole 16-byte ALSA frames at 192 kHz / 8 ch
    (per-device capability check, automatic fallback when the receiver
    is not HBR-capable)
  • Software volume Q15 scaling on the PCM path, bypassed for passthrough
  • Dual-log to /tmp/dream_audio.log (same reason as dream_video)

container/container_ffmpeg.c

  • HLS-only HTTP read tuning (longer connect / recv windows)
  • Local-file probesize + max_analyze_duration caps so MP4 / MKV opens don't stall scanning thousands of streams
  • TrueHD demux packets routed to the existing TrueHD writer
  • Video buffers flushed on OUTPUT_FLUSH / OUTPUT_CLEAR
  • The seconds-seek branch's output->Command(OUTPUT_CLEAR) stays commented — that path runs every av_read_frame iteration that passes the gate, not the seek boundary, and turning it on starved the dream_audio queue on stitched HLS (PlutoTV vpts stuck for minutes, av_drift = -425000 ms)

main/exteplayer.c

  • Skip noprobe for HTTP(S) streams so the network player gets the container probe it needs

output/writer/mipsel/h264.c

  • Include config.h on mipsel so the build picks up HAVE_* feature flags

New output adapters that route exteplayer3 directly through the Dreambox-
private DVB-API + ALSA, matching the runtime behaviour of dreamvideosink /
dreamaudiosink as observed by strace. Replaces the BCM-style writer chain
for the AML targets; enabled by --enable-dreamnextgen.

output/dream_video.c
====================

  - VIDEO_SET_DEC_SYSINFO (48 B struct) + VIDEO_SET_FRAME (168 B struct,
    GstClockTime-style pts) on /dev/dvb/adapter0/video0
  - H.264 / H.265 / MPEG1/2 streamtype + dec_format mapping
  - Producer/consumer ring (256 slots) between FFMPEGThread and a
    dv_consumer thread; consumer burst-submits frames so the kernel
    ringbuffer carries 3-4 frames ahead (vstream_cache ~ 250 kB,
    buf_avail_num ~ 3) instead of the just-in-time 12 kB / buf=0 we got
    from a per-frame pacer. EAGAIN + poll(50 ms, 250 ms giveup) on
    /dev/dvb/.../video0 + /dev/amvideo_poll is the back-pressure
  - Stream PTS used directly so tsync's pts_video stays in the same
    timebase as pts_audio; monotonic 90 kHz fallback only when fr_pts < 0
  - VIDEO_GET_EVENT drain before SET_FRAME, VIDEO_GET_PTS after — mirrors
    dreamvideosink strace pattern. disable_video=0 on open, no
    freerun_mode / show_first_frame_nosync touch (also matches strace)
  - OUTPUT_FLUSH / OUTPUT_CLEAR drains the queue, VIDEO_CLEAR_BUFFER,
    writes tsync/discontinue=1
  - Dual logging (stderr + /tmp/dream_video.log) because serviceapp's
    PlayerApp::stderrAvail filters non-JSON stderr out of the e2 debug log

output/dream_audio.c
====================

  - ALSA PCM output on the dreamhdmi / dreamspdif / dreambt slave
    (selected by /sys/class/amhdmitx/amhdmitx0/audio_source)
  - FFmpeg software decoder feeding interleaved S16; rate / channels
    from pcmPrivateData_t shipped through extradata by container_ffmpeg.c
  - Producer/consumer queue (128 slots, 500 ms bounded push wait)
    between DreamAudioWrite (on FFMPEGThread) and a da_consumer thread;
    consumer owns the ALSA handle + drift logic so the demuxer never
    blocks in snd_pcm_writei. Solves the AAC drain-storm we measured on
    AAC live-TV AML mirrors (~30% drops without queue, ~5% with)
  - Match dreamaudiosink runtime: tsync ENABLED in PCRMASTER (mode=2),
    /proc/stb/pcr_offset = 0x0 + auto_pcr_offset = 0x0, pts_audio /
    pts_video wiped on Open, signal tsync/discontinue. AMASTER caused
    the kernel to release video at the audio-chunk arrival rate
    (~50 fps for our 20 ms chunks) and drop ~33% of 25 fps frames —
    visible as the "gefesselt" stutter
  - Initial anchor on the first chunk after Open / Flush / Switch:
      * |lead| > 2000ms          → ALSA flush, drop buffer (1s throttle)
      * lead in (+50, +2000]ms   → push lead silence (cap 2000)
      * lead in [-3000, -50)ms   → queue (-lead) bytes of skip budget
    Sustained-lag re-arm once anchor disarmed: |av_ms| > 1000 held 2s
    re-arms (5s cooldown). 30s heartbeat log; no per-write logging.
  - da_reset_anchor_locked() called from Stop / Flush / Switch — mirror
    of dream_alsa_reset_anchor(). Without it, post-seek the drift code
    computed apts_speaker vs a stale pts_video (kernel display still on
    the pre-seek frame until the first I-frame decodes)
  - Decoded audio rate compared against a separate m_alsa_dec_rate so
    the HW-promoted rate from snd_pcm_hw_params_set_rate_near
    (44100 → 48000) doesn't trigger a configure-loop on AAC 44.1 kHz
    Live-TV streams
  - IEC61937 passthrough for AC3 / EAC3 / DTS via byte-swap into a
    static SPDIF buffer; TrueHD / DTS-HD MA HBR via a libavformat spdif
    muxer producing whole 16-byte ALSA frames at 192 kHz / 8 ch
    (per-device capability check, automatic fallback when the receiver
    is not HBR-capable)
  - Software volume Q15 scaling on the PCM path, bypassed for passthrough
  - Dual-log to /tmp/dream_audio.log (same reason as dream_video)

container/container_ffmpeg.c
============================

  - HLS-only HTTP read tuning (longer connect / recv windows)
  - Local-file probesize + max_analyze_duration caps so MP4 / MKV opens
    don't stall scanning thousands of streams
  - TrueHD demux packets routed to the existing TrueHD writer
  - Video buffers flushed on OUTPUT_FLUSH / OUTPUT_CLEAR
  - The seconds-seek branch's output->Command(OUTPUT_CLEAR) stays
    commented — that path runs every av_read_frame iteration that
    passes the gate, not the seek boundary, and turning it on starved
    the dream_audio queue on stitched HLS (PlutoTV vpts stuck for
    minutes, av_drift = -425000 ms)

main/exteplayer.c
=================

  - Skip noprobe for HTTP(S) streams so the network player gets the
    container probe it needs

output/writer/mipsel/h264.c
===========================

  - Include config.h on mipsel so the build picks up HAVE_* feature flags
Comment thread output/dream_audio.c Fixed
Comment thread output/dream_video.c Fixed
Comment thread main/exteplayer.c Fixed
When the kernel video decoder stalls (DASH segment underrun on hr-live
etc.) pts_video stops advancing. The anchor would otherwise see growing
av-drift and fire HUGE-gap → ALSA flush → 2000ms silence push → re-arm
in a loop every few seconds, audibly chopping audio while video is
stuck anyway.

Track pts_video changes per anchor read. When the same value has been
seen for >2s, skip the flush / silence-push / sustained-lag re-arm —
audio plays through normally. Heartbeat logs " VFROZEN" so this stays
visible. When the decoder recovers and pts_video advances again, the
anchor resumes normal correction (gentle skip if drift accumulated).

Reset state lands in DreamAudioOpen and da_reset_anchor_locked so seeks
and channel changes start fresh.
Comment thread output/dream_audio.c Fixed
Comment thread output/dream_video.c Fixed
S5443 is a pattern rule on the "/tmp/..." literal. We already opened
the file with O_NOFOLLOW | O_CLOEXEC and mode 0600 in 13878c8 —
which is the actual mitigation — but the rule does not inspect open
flags, so it kept warning. Mark the two opens NOSONAR with a note
explaining why the mitigation already covers the threat.

[DreamNextGen] harden /tmp log opens against symlink-race

SonarRule S5443: fopen("/tmp/dream_*.log", "a") is flagged because /tmp
is a publicly writable directory and an attacker could pre-create a
symlink at that path. On the receiver /tmp is a single-user tmpfs so
the threat is theoretical, but the mitigation is free:

  fopen("a") -> open(O_WRONLY|O_CREAT|O_APPEND|O_NOFOLLOW|O_CLOEXEC,0600)
                + fdopen()

O_NOFOLLOW refuses to follow a pre-existing symlink, 0600 makes the
file private, O_CLOEXEC keeps it out of children spawned by exec().
Both files already include <fcntl.h> and <unistd.h>.

Also annotate the http:// scheme prefix-match in exteplayer.c (Sonar
S5332): exteplayer3 is the URL consumer, not the transport chooser.
The literal "http://" is matched to decide whether to skip ffmpeg's
noprobe shortcut; it is not used to open any HTTP socket. // NOSONAR.
@WXbet
WXbet force-pushed the aml-audio-fixes branch from 13878c8 to 137344e Compare June 17, 2026 16:13
@sonarqubecloud

Copy link
Copy Markdown

@atvcaptain
atvcaptain merged commit ca7150c into oe-alliance:master Jun 17, 2026
3 checks passed
@WXbet
WXbet deleted the aml-audio-fixes branch June 17, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants